/*
 * graphic.c
 *
 *  Created on: 2022年2月4日
 *      Author: TamGitsun
 */

#include "graphic.h"
#include "font.h"
#include "fsl_debug_console.h"


void draw_line(int x0, int y0, int x1, int y1,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH], uint32_t color)
{
	int delta_x = x1 - x0 + 1;
	int delta_y = y1 - y0 + 1;
	if (delta_x < 0)
	{
		delta_x = -delta_x;
	}
	if (delta_y < 0)
	{
		delta_y = -delta_y;
	}
	int distance = delta_x > delta_y ? delta_x : delta_y;
	int draw_x = x0, draw_y = y0;
	int temp_x = 0, temp_y = 0;
	for (int i = 0; i < distance; ++i)
	{
		frameBuffer[APP_IMG_HEIGHT - draw_y - 1][draw_x] = color;
		temp_x += delta_x;
		if (temp_x > distance)
		{
			temp_x -= distance;
			if (x1 >= x0)
			{
				++draw_x;
			} else
			{
				--draw_x;
			}
		}
		temp_y += delta_y;
		if (temp_y > distance)
		{
			temp_y -= distance;
			if (y1 >= y0)
			{
				++draw_y;
			} else
			{
				--draw_y;
			}
		}
	}
}

void draw_char(int x, int y, char ch, int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	if((x > (APP_IMG_WIDTH - font_size / 2)) ||
        (y > (APP_IMG_HEIGHT - font_size)))
	{
		return;
	}
	ch -= ' ';
	switch (font_size)
	{
	case 12: {
		for (int i = 0; i < 12; ++i)
		{
			int temp = asc2_1206[ch][i];
			for (int j = 0; j < 6; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (12 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (12 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
		}
		break;
	}
	case 16: {
		for (int i = 0; i < 16; ++i)
		{
			int temp = asc2_1608[ch][i];
			for (int j = 0; j < 8; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (16 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (16 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
		}
		break;
	}
	case 32: {
		for (int i = 0; i < 32; ++i)
		{
			int temp = asc2_3216[ch][i << 1];
			for (int j = 0; j < 8; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (32 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (32 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
			temp = asc2_3216[ch][(i << 1) + 1];
			for (int j = 8; j < 16; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (32 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (32 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
		}
		break;
	}
	case 24: {
		for (int i = 0; i < 24; ++i)
		{
			int temp = asc2_2412[ch][i << 1];
			for (int j = 0; j < 8; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (24 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (24 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
			temp = asc2_2412[ch][(i << 1) + 1];
			for (int j = 8; j < 12; ++j)
			{
				if ((temp & 0x80) > 0)
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (24 - i)][x + j] = font_color;
				} else
				{
					frameBuffer[APP_IMG_HEIGHT - y - 1 - (24 - i)][x + j] = bg_color;
				}
				temp <<= 1;
			}
		}
		break;
	}
	default:
		PRINTF("Font size %d is not supported!\n", font_size);
		return;
	}
}

void draw_string(int x, int y, const char * str, int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	if (NULL == str)
	{
		return;
	}
	int n_chars = strlen(str);
	int x_offset_step = 0;
	switch (font_size)
	{
	case 12:
	case 16:
	case 24:
	case 32:
		x_offset_step = font_size >> 1;
		break;
	default:
		PRINTF("Font size %d is not supported!\n", font_size);
		return;
	}
	for (int i = 0; i < n_chars; ++i)
	{
		draw_char(x, y, str[i], font_size, frameBuffer, font_color, bg_color);
		x += x_offset_step;
	}
}

void draw_string_right_align(int x, int y, const char * str, int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	draw_string(x - strlen(str) * (font_size >> 1), y,
		str, font_size, frameBuffer, font_color, bg_color);
}

void draw_string_h_center_align(int x, int y, const char * str, int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	int len = strlen(str);
	x -= ((len * font_size) >> 2);  // (len / 2) * (font_size / 2)
	if ((len & 0x01) > 0)  // Odd
	{
		x -= (font_size >> 2);  // Left shift half a char
	}
	draw_string(x, y, str, font_size, frameBuffer, font_color, bg_color);
}

void draw_string_v_center_align(int x, int y, const char * str, int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	draw_string(x, y - (font_size >> 1), str, font_size, frameBuffer,
        font_color, bg_color);
}

void draw_string_v_center_right_align(int x, int y, const char * str,
        int font_size,
		uint32_t frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH],
		uint32_t font_color, uint32_t bg_color)
{
	draw_string(x - strlen(str) * (font_size >> 1), y - (font_size >> 1),
		str, font_size, frameBuffer, font_color, bg_color);
}
